<template>
  <div class="drag-list-item" :class="classObject" draggable="true" @dragstart="dragstart" @dragend="dragend" @drop="onDrop" @dragover="dragover" @dragleave="dragleave">
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
import { ref, computed } from "vue";

const props = defineProps({
  data: {
    type: Object,
    default: () => { }
  },
  ratio: {
    type: Number,
    default: 0.3
  },
})

const dragType = ref('')
const isDrag = ref(false)

const classObject = computed(() => ({
  'is-drag': isDrag.value,
  'drag-top': dragType.value === 'top',
  'drag-middle': dragType.value === 'middle',
  'drag-bottom': dragType.value === 'bottom',
}))

const emits = defineEmits(['dragDrop'])
function onDrop(e: any) {
  e.stopPropagation()
  let data = e.dataTransfer.getData('data')
  data = JSON.parse(data)
  emits('dragDrop', dragType.value, data)
  dragType.value = ''
}

function dragstart(e: any) {
  e.stopPropagation()
  isDrag.value = true
  e.dataTransfer.setData('data', JSON.stringify(props.data))
}

function dragend() {
  isDrag.value = false
}

function dragover(e: any) {
  e.preventDefault()
  if (isDrag.value) {
    return
  }
  const height = e.target.offsetHeight
  if (e.offsetY < height * props.ratio) {
    dragType.value = 'top'
  } else if (e.offsetY > height * (1 - props.ratio)) {
    dragType.value = 'bottom'
  } else {
    dragType.value = 'middle'
  }
}

function dragleave() {
  dragType.value = ''
}
</script>
<style lang="less">
.drag-list-item {
  position: relative;

  * {
    pointer-events: none;
  }

  &.is-drag,
  &.drag-top,
  &.drag-middle,
  &.drag-bottom {
    * {
      pointer-events: none !important;
    }
  }

  &.drag-middle {
    background-color: rgba(71, 123, 246, 0.3) !important;
  }

  &.drag-top::before,
  &.drag-bottom::before {
    content: '';
    width: 100%;
    height: 2px;
    background-color: rgba(71, 123, 246, 0.9);
    position: absolute;
    left: 0;
    top: 0;
  }

  &.drag-bottom::before {
    top: auto;
    bottom: 0;
  }
}
</style>
